package cn.com.twoke.application.game.mario.game.system;

import cn.com.twoke.application.game.mario.core.ecs.component.ColliderComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.PositionComponent;
import cn.com.twoke.application.game.mario.core.ecs.entity.Entity;
import cn.com.twoke.application.game.mario.core.ecs.system.LogicGameSystem;
import cn.com.twoke.application.game.mario.game.component.PlayerComponent;
import cn.com.twoke.application.game.mario.game.component.SceneComponent;
import cn.com.twoke.application.game.mario.game.component.TransfersComponent;
import cn.com.twoke.application.game.mario.game.util.PlayerUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.Function;

/**
 * 传送门系统
 */
@Slf4j
public class TransfersSystem implements LogicGameSystem {

    private final Map<String, TransfersComponent.Transfer> transfersComponentMap = new HashMap<String, TransfersComponent.Transfer>();

    @Override
    public void update(List<Entity> entities, double delta) {
        try {
            Optional<Entity> playerOpt = Optional.ofNullable(PlayerUtils.getPlayer(entities));
            if (playerOpt.isPresent()) {
                Entity entity = playerOpt.get();
                ColliderComponent collider = entity.getComponent(ColliderComponent.class);
                PlayerComponent playerComponent = entity.getComponent(PlayerComponent.class);
                for (TransfersComponent.Transfer value : transfersComponentMap.values()) {
                    try {
                        if (collider.shape.get().intersects(value.getShape().getBounds()) // 是否存在碰撞
                                && value.enabled // 传送门是否开启
                                && value.type == TransfersComponent.TransferType.ENTRY // 传送门类型是否为入口
                                && !value.used // 传送门是使用
                                && checkinInputState(value, playerComponent)) {

                            value.used = true;
                            Function<Entity, String> checkinFun = value.getCheckinFun();
                            if (Objects.isNull(checkinFun)) {
                                // 获取出口位置
                                TransfersComponent.Transfer transfer = transfersComponentMap.get(value.getExportKey());
                                if (transfer != null) {
                                    // 设置玩家到出口位置的地址
                                    PositionComponent positionComponent = entity.getComponent(PositionComponent.class);
                                    SceneComponent sceneComponent = entity.getComponent(SceneComponent.class);
                                    positionComponent.x = transfer.shape.getBounds().x;
                                    positionComponent.y = transfer.shape.getBounds().y;
                                    sceneComponent.setName(transfer.getTargetSceneName());
                                } else {
                                    log.warn("Transfer not found for key: {}", value.getExportKey());
                                }
                            } else {
                                SceneComponent sceneComponent = entity.getComponent(SceneComponent.class);
                                sceneComponent.setName(checkinFun.apply(entity));
                            }
                            value.used = false;
                            break;
                        }
                    } catch (Exception e) {
                        log.error("Error processing transfer: {}", value.getKey(), e);
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error updating transfers system", e);
        }
    }

    private boolean checkinInputState(TransfersComponent.Transfer value, PlayerComponent playerComponent) {
        return (playerComponent.isDown && value.direction == TransfersComponent.Direction.TOP) || (playerComponent.isRight && value.direction == TransfersComponent.Direction.LEFT);
    }

    public void register(TransfersComponent component) {
        for (TransfersComponent.Transfer entry : component.getEntries()) {
            transfersComponentMap.put(entry.getKey(), entry);
        }
    }
}
